package com.foreverwin.jzymes.production.debur.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.foreverwin.jzymes.common.constant.Constants;
import com.foreverwin.jzymes.common.service.*;
import com.foreverwin.jzymes.common.util.BOHandleUtil;
import com.foreverwin.jzymes.common.util.CommonMethods;
import com.foreverwin.jzymes.framework.exception.BusinessException;
import com.foreverwin.jzymes.framework.util.DateUtil;
import com.foreverwin.jzymes.framework.util.HttpClientUtils;
import com.foreverwin.jzymes.framework.util.I18nUtil;
import com.foreverwin.jzymes.production.debur.domain.PackLog;
import com.foreverwin.jzymes.production.debur.domain.PrintLog;
import com.foreverwin.jzymes.production.debur.mapper.PackLogAdviceMapper;
import com.foreverwin.jzymes.production.debur.mapper.PackLogMapper;
import com.foreverwin.jzymes.production.debur.mapper.PrintLogMapper;
import com.foreverwin.jzymes.production.debur.service.IDeburPackAdviceService;
import com.sap.me.common.NameValueObject;
import com.sap.me.extension.Services;
import com.sap.me.frame.transitionutils.Exceptions;
import com.sap.me.numbering.GenerateNextNumberRequest;
import com.sap.me.numbering.GenerateNextNumberResponse;
import com.sap.me.numbering.NextNumberTypeEnum;
import com.sap.me.numbering.NumberingServiceInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.util.*;

@Service
public class DeburPackAdviceServiceImpl implements IDeburPackAdviceService {
    @Autowired
    ISiteAdviceService siteAdviceService;
    @Autowired
    IResourceAdviceService resourceAdviceService;
    @Autowired
    IContainerAdviceService containerAdviceService;
    @Autowired
    ICommonService commonService;
    @Autowired
    IItemAdviceService itemAdviceService;
    @Autowired
    ISystemRuleAdviceService systemRuleAdviceService;
    @Autowired
    ICustomFieldsAdviceService customFieldsAdviceService;
    @Autowired
    IItemGroupAdviceService itemGroupAdviceService;
    @Autowired
    IProductionShiftService productionShiftService;
    @Autowired
    PackLogMapper packLogMapper;
    @Autowired
    PrintLogMapper printLogMapper;
    @Autowired
    PackLogAdviceMapper packLogAdviceMapper;

    /**
     * 包装产品并打印
     *
     * @param packLog
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void packItem( PackLog packLog ){

        /**检查包装记录字段*/
        checkFieldsForPack( packLog );

        /**查询工序*/
        String operation = resourceAdviceService.findOperationByResource( packLog.getSite(), packLog.getResrce() );

        /**查询机种*/
        packLog.setMachineType( commonService.findItemGroupByItem( packLog.getSite(), packLog.getItemBo() ) );
        packLog.setCreatedDateTime( new Date() );

        String itemBo = commonService.findSfcItemByItem( packLog.getSite(), packLog.getItemBo() );

        /**保存过站记录、批次过站数量*/
        commonService.sfcPassByQty( packLog.getSite(), itemBo, null, null, packLog.getResrce(), operation, packLog.getPackQty(), packLog.getCreatedDateTime() );

        /**保存包装记录*/
        //packLog.setContainerNumber( "B201900404A001" );
        packLog.setContainerNumber( createContainerNumber( packLog.getSite(), packLog.getContainer(), itemBo ) );
        packLog.setCreateUserBo( CommonMethods.getUserBo() );
        packLog.setHandle( BOHandleUtil.buildPackLogHandle( packLog.getItemBo(), packLog.getResrce(), packLog.getCreatedDateTime() ) );
        packLogMapper.insertPackLog( packLog );

        /**打印标签，保存打印标签记录*/
        printLabel( packLog );
    }

    /**
     * 创建箱号
     *
     * @param site
     * @param container
     * @return
     */
    public String createContainerNumber( String site, String container, String itemBo ){
        String containerNumber = null;
        try{
            NumberingServiceInterface numberingService = Services.getService( "com.sap.me.numbering", "NumberingService", site );
            GenerateNextNumberRequest nextNumberRequest = new GenerateNextNumberRequest();
            nextNumberRequest.setNextNumberType( NextNumberTypeEnum.CONTAINER );
            nextNumberRequest.setNumberOfValues( BigDecimal.ONE );
            nextNumberRequest.setContainerRef( BOHandleUtil.buildContainerHandle( site, container ) );
            List<NameValueObject> customFields = new ArrayList<>();
            customFields.add( new NameValueObject( "ITEM_LABEL", customFieldsAdviceService.existCustomValue( itemBo, Constants.ITEM_CUSTOM_FIELD_ITEM_LABEL ) ) );
            customFields.add( new NameValueObject( "SHIFT", productionShiftService.findShift( site, new Date() ) ) );
            nextNumberRequest.setCustomFields( customFields );

            GenerateNextNumberResponse nextNumberResponse = numberingService.generateNextNumber( nextNumberRequest );
            containerNumber = nextNumberResponse.getId().get(0);
        }catch (com.sap.me.frame.domain.BusinessException e){
            throw BusinessException.build( Exceptions.convert( e ).toString() );
        }
        return containerNumber;
    }



    /**
     * 打印标签
     *
     * @param packLog
     */
    public void printLabel( PackLog packLog ) {
        Map<String,Object> itemMap = itemAdviceService.existItem( packLog.getItemBo() );
        String containerBo = BOHandleUtil.buildContainerHandle( packLog.getSite(), packLog.getContainer() );

        String item = (String) itemMap.get("ITEM");
        String itemDesc = (String) itemMap.get( "DESCRIPTION" );
        String containerNo = packLog.getContainerNumber();
        Long packQty = packLog.getPackQty();
        String printDate = DateUtil.format( packLog.getCreatedDateTime(), "yyyy-MM-dd" );
        String shift = productionShiftService.findShift( packLog.getSite(), packLog.getCreatedDateTime() );

        Map<String,Object> printMap = new HashMap<>();
        printMap.put( "ITEM", item );
        printMap.put( "ITEM_DESC", itemDesc );
        printMap.put( "CONTAINER_NO", containerNo );
        printMap.put( "PACK_QTY", packQty );
        printMap.put( "PRINT_DATE", printDate );
        printMap.put( "SHIFT", shift );

        List<Map<String,Object>> printData = new ArrayList<>();
        printData.add( printMap );

        Map<String,Object> printRequest = new HashMap<>();
        printRequest.put( "PRINT_NAME", customFieldsAdviceService.existCustomValue( containerBo, Constants.CONTAINER_CUSTOM_FIELD_PRINTER ) );
        printRequest.put( "LABEL_QTY", 1 );
        printRequest.put( "TEMPLATE", customFieldsAdviceService.existCustomValue( containerBo, Constants.CONTAINER_CUSTOM_FIELD_PRINT_TEMPLATE ) );
        printRequest.put( "PRINT_DATA", printData );

        Map<String,Object> requestData = new HashMap<>();
        requestData.put( "PRINT_REQUEST", printRequest );

        String printServer = systemRuleAdviceService.existSystemRule( packLog.getSite(), Constants.SYSTEM_RULE_PRINT_SERVER );
        String requestBody = null;
        try{
            requestBody = "REQUEST_DATA=" + new ObjectMapper().writeValueAsString( requestData );
        }catch ( JsonProcessingException e ){
            throw BusinessException.build( e.getMessage() );
        }

        ResponseEntity responseEntity = HttpClientUtils.callPost( printServer, requestBody );

        /**保存打印记录*/
        PrintLog printLog = new PrintLog();
        printLog.setSite( packLog.getSite() );
        printLog.setHttpUrl( printServer );
        printLog.setPrintParam( requestBody );
        printLog.setStatusCode( responseEntity.getStatusCode().toString() );
        printLog.setCreatedDateTime( new Date() );
        printLog.setCreateUserBo( CommonMethods.getUserBo() );
        printLog.setHandle( UUID.randomUUID().toString() );
        printLogMapper.insertPrintLog( printLog );
    }


    /**
     * 标签补打
     *
     * @param packLog
     */
    @Transactional( propagation = Propagation.REQUIRED, rollbackFor = Exception.class )
    public void reprintLabel( PackLog packLog ){
        /**检查物料*/
        itemAdviceService.existItem( packLog.getItemBo() );
        /**检查箱号*/
        Assert.hasText( packLog.getContainerNumber(), I18nUtil.getI18nText( "production.debur.containerNumberNotBlank" ) );

        PackLog _packLog = packLogAdviceMapper.selectPackLog( packLog.getItemBo(), packLog.getContainerNumber() );
        if( _packLog == null ){
            throw BusinessException.build( "production.debur.packLogNotExist", new String[]{ packLog.getItemBo(), packLog.getContainerNumber() } );
        }

        /**打印标签*/
        printLabel( _packLog );
    }

    /**
     * 查询物料包装记录
     *
     * @param itemBo
     * @return
     */
    public List<PackLog> findItemPackLog( String itemBo, String containerNumber ){
        PackLog queryParam = new PackLog();
        queryParam.setSite( CommonMethods.getSite() );
        queryParam.setItemBo( itemBo );
        queryParam.setContainerNumber( containerNumber );
        List<PackLog> packLogList = packLogAdviceMapper.selectPackLogList( queryParam );
        return packLogList;
    }

    public void checkFieldsForPack( PackLog packLog ){
        /**检查站点*/
        siteAdviceService.existSite( packLog.getSite() );
        /**检查物料*/
        itemAdviceService.existItem( packLog.getItemBo() );
        /**检查设备*/
        resourceAdviceService.existResource( packLog.getSite(), packLog.getResrce() );
        /**检查包装容器*/
        containerAdviceService.existContainer( packLog.getSite(), packLog.getContainer() );
        /**检查包装数量*/
        Assert.isTrue( packLog.getPackQty() != null && packLog.getPackQty() > 0 , I18nUtil.getI18nText( "production.debur.packQtyNotValid", new Object[]{ packLog.getPackQty() } ) );
        /**检查包装规则*/
        Assert.isTrue( packLog.getMaxQty() != null && packLog.getMaxQty() > 0 , I18nUtil.getI18nText( "production.debur.maxQtyNotValid", new Object[]{ packLog.getMaxQty() } ) );
        /**检查包装数量是否超过包装规格*/
        Assert.isTrue( packLog.getPackQty() <= packLog.getMaxQty() , I18nUtil.getI18nText( "production.debur.packQtyExceedMaxQty", new Object[]{ packLog.getPackQty(), packLog.getMaxQty() } ) );
    }
}
